package main

import (
	"fmt"
	"log"
	"os"
	"path"
	"strings"
	"time"

	"thumbnail/lib/fs"
	"thumbnail/lib/img"

	"github.com/urfave/cli/v2"
)

var (
	// 当前版本号
	version = ""
	// 编译时间
	buildtime = ""
	// 应用名
	appname = ""
)

var width uint = 100
var height uint = 100
var quality = 50
var typeCommand string
var outdir string
var indir string
var maxWidth uint = 750

const typeCommandCompress = "compress"

func printErrAndExit(e error) {
	fmt.Println("出现错误:", e.Error())
	os.Exit(0)
}
func deal(fileOrDir string) (e error) {
	if fs.IsFileExists(fileOrDir) {
		stat, _ := os.Stat(fileOrDir)
		if stat.IsDir() {
			dealDir(fileOrDir, true)
		} else {
			dealFile(fileOrDir, true)
		}
	} else {
		e = fmt.Errorf("[%s]不存在", fileOrDir)
	}
	if e != nil {
		printErrAndExit(e)
	}
	return
}
func dealFile(file string, fromDeal bool) (e error) {
	if !fromDeal {
		if !fs.IsFileExists(file) {
			printErrAndExit(fmt.Errorf("文件[%s]不存在", file))
			return
		}
		stat, _ := os.Stat(file)
		if stat.IsDir() {
			printErrAndExit(fmt.Errorf("[%s]不是文件", file))
			return
		}
	}

	fInfo, _ := os.Stat(file)
	log.Println("开始处理:", file, fInfo.Size())

	indir := path.Dir(file)
	var dirTo string
	if "" == outdir {
		dirTo = path.Dir(file) + "_s"
	} else {
		dirTo = strings.Replace(path.Dir(file), indir, outdir, -1)
	}

	fs.Mkdirp(dirTo)
	fileTo := path.Join(dirTo, path.Base(file))

	if typeCommand == typeCommandCompress {
		_, e = img.Compress(file, fileTo, 0, 0, quality, maxWidth)
	} else {
		_, e = img.GetImageThumb(file, fileTo, width, height, quality)
	}

	if e != nil {
		log.Printf("处理[%s]出现错误:%v\n", file, e)
	} else {
		ftoInfo, _ := os.Stat(fileTo)
		log.Printf("生成[%s], 大小: %v 体积为原来的: %v\n", fileTo, ftoInfo.Size(), float64(ftoInfo.Size())/float64(fInfo.Size()))
	}
	return
}
func dealDir(dir string, fromDeal bool) (e error) {
	if !fromDeal {
		if !fs.IsFileExists(dir) {
			printErrAndExit(fmt.Errorf("目录[%s]不存在", dir))
			return
		}
		stat, _ := os.Stat(dir)
		if !stat.IsDir() {
			printErrAndExit(fmt.Errorf("[%s]不是目录", dir))
			return
		}
	}

	list, e1 := os.ReadDir(dir)
	if e1 != nil {
		printErrAndExit(fmt.Errorf("读取目录[%s]出现错误: %v", dir, e1))
		return
	}

	for _, file := range list {
		p := path.Join(dir, file.Name())
		if file.IsDir() {
			dealDir(p, true)
		} else {
			dealFile(p, true)
		}
	}
	return
}
func getConf(c *cli.Context) {
	w := c.Uint("width")
	if w > 0 {
		width = w
	}
	mw := c.Uint("max-width")
	if mw >= 0 {
		maxWidth = mw
	}
	h := c.Uint("height")
	if h > 0 {
		height = h
	}
	q := c.Int("quality")
	if q > 0 {
		quality = q
	}
	outdir = c.String("outdir")
	if outdir == "" {
		outdir = indir
	}
	typeCommand = c.String("type")
	if typeCommand != typeCommandCompress {
		typeCommand = "thumbnail"
	}

	if "" != outdir {
		outdir = path.Clean(outdir)
	}

	// fmt.Println(width, height, maxWidth, quality, typeCommand, outdir)
}
func main() {
	app := cli.NewApp()
	app.Usage = "生成缩略图"

	app.Flags = []cli.Flag{
		&cli.UintFlag{
			Name:    "width",
			Aliases: []string{"w"},
			Usage:   "width of thumbnail",
		},
		&cli.UintFlag{
			Name:    "height",
			Aliases: []string{"hh"},
			Usage:   "height of thumbnail",
		},
		&cli.IntFlag{
			Name:    "quality",
			Aliases: []string{"q"},
			Usage:   "quality of thumbnail",
		},
		&cli.StringFlag{
			Name:    "outdir",
			Aliases: []string{"o"},
			Usage:   "output dir",
		},
	}
	app.Action = func(c *cli.Context) error {
		getConf(c)
		return deal(c.Args().First())
	}
	app.Commands = append(app.Commands,
		&cli.Command{
			Name:        "compress",
			Aliases:     []string{"c"},
			Usage:       "compress image",
			UsageText:   "[global options] compress [options] dir/file",
			Description: "compress image",
			Flags: []cli.Flag{
				&cli.UintFlag{
					Name:        "max-width",
					Aliases:     []string{"mw"},
					DefaultText: fmt.Sprintf("%d", maxWidth),
					Usage:       "max-width of thumbnail",
				},
			},
			Action: func(c *cli.Context) error {
				typeCommand = typeCommandCompress
				getConf(c)
				return deal(c.Args().First())
			},
		})
	if version == "" {
		version = "development"
	}
	if buildtime == "" {
		buildtime = time.Now().Format("20060102150405")
	}
	app.Version = version + "(" + buildtime + ")"
	app.Run(os.Args)
}
